package com.bjb.vr.common.service;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bjb.vr.common.ao.SysTenantAo;
import com.bjb.vr.common.ao.UmsAccountAo;
import com.bjb.vr.common.constant.Constants;
import com.bjb.vr.common.constant.RoleConstants;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.*;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.SysTenantVo;
import com.bjb.vr.common.vo.UmsAccountVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * @description: 客户管理模块
 * @author: hujingbo
 * @create: 2022-08-19 15:16
 **/
@Slf4j
@Service
public class OptCustomerService {

    private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Resource
    private SysTenantMapper sysTenantMapper;

    @Resource
    private UmsAccountService accountService;

    @Resource
    private UmsAccountMapper umsAccountMapper;

    @Resource
    private UmsOptAccountMapper optAccountMapper;

    @Resource
    private UmsRoleMapper umsRoleMapper;

    @Resource
    private UmsUserRoleMapper umsUserRoleMapper;

    @Resource
    private ResDictionaryService dictionaryService;

    @Resource
    private SyncTenantService syncTenantService;

    @Resource
    private SysConfigService sysConfigService;

    /**
     * 查询客户信息--层级树
     *
     * @param tenantAo
     * @return
     */
    public List<SysTenantVo> queryCustomersTree(SysTenantAo tenantAo) {
        LambdaQueryWrapper<SysTenant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(tenantAo.getTenantName()), SysTenant::getTenantName, tenantAo.getTenantName());
        queryWrapper.eq(Objects.nonNull(tenantAo.getStatus()), SysTenant::getStatus, tenantAo.getStatus());
        List<SysTenant> sysTenants = sysTenantMapper.selectList(queryWrapper);
        List<SysTenantVo> sysTenantVos = buildShowData(sysTenants);
        return sysTenantVos;
    }

    /**
     * 封装前端展示的层级关系
     *
     * @param sysTenants
     * @return
     */
    private List<SysTenantVo> buildShowData(List<SysTenant> sysTenants) {
        // 过滤数据
        List<SysTenantVo> parentsList = new ArrayList<>();
        List<SysTenantVo> childrenList = new ArrayList<>();
        sysTenants.stream().forEach(ss -> {
            if (ss.getParentId() == 0) {
                SysTenantVo sysTenantVo = new SysTenantVo();
                BeanUtils.copyProperties(ss, sysTenantVo);
                parentsList.add(sysTenantVo);
            } else {
                SysTenantVo sysTenantVo = new SysTenantVo();
                BeanUtils.copyProperties(ss, sysTenantVo);
                childrenList.add(sysTenantVo);
            }
        });

        // 如果插叙条件是从中间查询，那么此时parentsList集合可能为空，那么需要从childrenList获取最顶级的节点当做父节点
        if (parentsList.size() == 0) {
            List<SysTenantVo> tempList = new ArrayList<>();
            tempList.addAll(childrenList);
            for (SysTenantVo sysTenantVo : childrenList) {
                confirmParentNode(sysTenantVo, tempList);
            }
            // 设置最后的父节点数据
            parentsList.addAll(tempList);
        }

        // 封装子节点数据
        parentsList.stream().forEach(pp -> {
            List<SysTenantVo> sysTenantVos = buildChildrenData(pp, childrenList);
            pp.setChildren(sysTenantVos);
            // 封装客户地址
            if (StringUtils.isNotBlank(pp.getAddress())) {
                String[] split = pp.getAddress().split(":");
                pp.setAddress(split[0].equals("null") ? null : split[0]);
                pp.setDetailAddress(split[1].equals("null") ? null : split[1]);
            }
            // 封装客户类别
            if (StringUtils.isNotBlank(pp.getCategory())) {
                ResDictionary dictionary = dictionaryService.getResDictionaryByCode(pp.getCategory());
                pp.setCategoryName(dictionary.getDictName());
            }
        });
        return parentsList;
    }

    /**
     * 保留最顶层父节点数据
     *
     * @param sysTenantVo
     * @param tempList
     * @return
     */
    private void confirmParentNode(SysTenantVo sysTenantVo, List<SysTenantVo> tempList) {
        Iterator<SysTenantVo> iterator = tempList.iterator();
        while (iterator.hasNext()) {
            SysTenantVo next = iterator.next();
            if (sysTenantVo.getId().equals(next.getParentId())) {
                iterator.remove();
            }
        }
    }

    /**
     * 递归设置子节点数据
     *
     * @param parentData
     * @param childrenList
     * @return
     */
    private List<SysTenantVo> buildChildrenData(SysTenantVo parentData, List<SysTenantVo> childrenList) {
        List<SysTenantVo> treeList = new ArrayList<>();
        childrenList.stream().forEach(cc -> {
            // 判断当前父节点是否有子节点
            if (parentData.getId().equals(cc.getParentId())) {
                cc.setChildren(buildChildrenData(cc, childrenList));
                // 封装客户地址
                if (StringUtils.isNotBlank(cc.getAddress())) {
                    String[] split = cc.getAddress().split(":");
                    cc.setAddress(split[0]);
                    cc.setDetailAddress(split[1]);
                }
                // 封装客户类别
                if (StringUtils.isNotBlank(cc.getCategory())){
                    ResDictionary dictionary = dictionaryService.getResDictionaryByCode(cc.getCategory());
                    cc.setCategoryName(dictionary.getDictName());
                }
                treeList.add(cc);
            }
        });
        return treeList;
    }

    /**
     * 新增客户信息
     *
     * @param tenantAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addCustomer(SysTenantAo tenantAo) {
        try {
            // 封装租户信息
            String tenantIdNo = UUID.fastUUID().toString().split("-")[4];
            UmsAccountAo umsAccountAo = new UmsAccountAo();
            BeanUtils.copyProperties(tenantAo, umsAccountAo);
            umsAccountAo.setUserName(tenantAo.getMobile());
            umsAccountAo.setPassword(tenantAo.getMobile() + Constants.INIT_PASS_SUFFIX);
            umsAccountAo.setNickName(tenantAo.getTenantName());
            umsAccountAo.setTenantId(tenantIdNo);
            umsAccountAo.setParentId(tenantAo.getParentId());
            if (Constants.ADDRESS_VALUE.equals(tenantAo.getAddress())) {
                umsAccountAo.setAddress(null);
            }
            if (Constants.ADDRESS_VALUE.equals(tenantAo.getDetailAddress())) {
                umsAccountAo.setAddress(umsAccountAo.getAddress() + ":" + null);
            }else {
                umsAccountAo.setAddress(umsAccountAo.getAddress() + ":" + tenantAo.getDetailAddress());
            }
            umsAccountAo.setAddressCode(tenantAo.getAddressCode());
            // 保存客户信息
            accountService.addManagerTenant(umsAccountAo);
            syncTenantService.addAuthTenant(umsAccountAo);
            sysConfigService.addTenantInfo(umsAccountAo);
            return true;
        } catch (BeansException e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 修改客户信息
     *
     * @param tenantAo
     * @return
     */
    public boolean updateCustomer(SysTenantAo tenantAo) {
        try {
            // 封装租户信息
            SysTenant sysTenant = new SysTenant();
            BeanUtils.copyProperties(tenantAo, sysTenant);
            if (StringUtils.isNotBlank(tenantAo.getAddress()) && StringUtils.isNotBlank(tenantAo.getDetailAddress())) {
                sysTenant.setAddress(tenantAo.getAddress() + ":" + tenantAo.getDetailAddress());
            }
            sysTenantMapper.updateById(sysTenant);
            // 如果状态不为空
            if (Objects.nonNull(tenantAo.getStatus())) {
                ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
                SysTenant sysTenantInfo = sysTenantMapper.selectById(tenantAo.getId());
                umsAccountMapper.updateAllAccountStatus(sysTenantInfo.getTenantId(), tenantAo.getStatus());
            }
            return true;
        } catch (BeansException e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 添加用户数据
     */
    public UmsAccount addUmsAccount(SysTenantAo tenantAo, SysTenant sysTenant){
        UmsAccountVo threadLocalAccount = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        // 放入线程变量
        threadLocalAccount.setTempTenantId(sysTenant.getTenantId());
        ThreadLocalUtil.set(ThreadLocalConstant.USER_ACCOUNT_INFO, threadLocalAccount);
        UmsAccount umsAccount = new UmsAccount();
        umsAccount.setTenantId(sysTenant.getTenantId());
        umsAccount.setUsername(tenantAo.getMobile());
        umsAccount.setPassword(passwordEncoder.encode(tenantAo.getMobile() + Constants.INIT_PASS_SUFFIX));
        umsAccount.setSuperMan(RoleConstants.SUPER_IDENTIFY);
        try {
            umsAccountMapper.insert(umsAccount);
            return umsAccount;
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 变更管理员
     *
     * @param tenantAo
     * @return
     */
    public boolean changeAdmin(SysTenantAo tenantAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        SysTenant sysTenant = sysTenantMapper.selectById(tenantAo.getId());
        // 判断新账号是否存在
        LambdaQueryWrapper<UmsAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsAccount::getUsername, tenantAo.getMobile());
        UmsAccount newUmsAccount = umsAccountMapper.selectOne(queryWrapper);

        // 查询旧账号信息
        LambdaQueryWrapper<UmsAccount> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(UmsAccount::getTenantId, sysTenant.getTenantId());
        queryWrapper2.eq(UmsAccount::getSuperMan, RoleConstants.SUPER_IDENTIFY);
        UmsAccount OldUmsAccount = umsAccountMapper.selectOne(queryWrapper2);

        try {
            // 添加新的账户信息
            if (newUmsAccount == null) {
                newUmsAccount = addUmsAccount(tenantAo, sysTenant);
            }

            // 如果账号一样，重置密码
            if (tenantAo.getMobile().equals(OldUmsAccount.getUsername())) {
                umsAccountMapper.updateNewAccount(sysTenant.getTenantId(), newUmsAccount.getUsername(), passwordEncoder.encode(newUmsAccount.getUsername() + Constants.INIT_PASS_SUFFIX));
                return true;
            }

            // 如果是旧账号有角色，先进行解绑
            LambdaQueryWrapper<UmsUserRole> umsUserRoleWrapper = new LambdaQueryWrapper<>();
            umsUserRoleWrapper.eq(UmsUserRole::getUserId, newUmsAccount.getUserId());
            UmsUserRole umsUserRole = umsUserRoleMapper.selectOne(umsUserRoleWrapper);
            if (umsUserRole != null){
                umsAccountMapper.deleteUmsUserRoleByUserIdAndRoleId(umsUserRole.getUserId(), umsUserRole.getRoleId());
                umsAccountMapper.deleteUmsRoleByRoleId(umsUserRole.getRoleId());
            }

            // 变更管理员账号信息
            umsAccountMapper.updateUmsUserRole(newUmsAccount.getUserId(), OldUmsAccount.getUserId());
            umsAccountMapper.updateOldAccount(sysTenant.getTenantId(), OldUmsAccount.getUsername());
            umsAccountMapper.updateNewAccount(sysTenant.getTenantId(), newUmsAccount.getUsername(), passwordEncoder.encode(newUmsAccount.getUsername() + Constants.INIT_PASS_SUFFIX));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 查询客户信息--列表
     *
     * @param tenantAo
     * @return
     */
    public List<SysTenantVo> queryCustomersList(SysTenantAo tenantAo) {
        LambdaQueryWrapper<SysTenant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(tenantAo.getTenantName()), SysTenant::getTenantName, tenantAo.getTenantName());
        queryWrapper.eq(Objects.nonNull(tenantAo.getStatus()), SysTenant::getStatus, tenantAo.getStatus());
        queryWrapper.orderByAsc(SysTenant::getId);
        List<SysTenant> sysTenants = sysTenantMapper.selectList(queryWrapper);
        List<SysTenantVo> sysTenantVos = new ArrayList<>();
        sysTenants.stream().forEach(ss -> {
            SysTenantVo sysTenantVo = new SysTenantVo();
            BeanUtils.copyProperties(ss, sysTenantVo);
            // 封装客户地址
            if (StringUtils.isNotBlank(ss.getAddress())) {
                String[] split = ss.getAddress().split(":");
                sysTenantVo.setAddress(split[0]);
                sysTenantVo.setDetailAddress(split[1]);
            }
            // 封装客户类别
            if (StringUtils.isNotBlank(ss.getCategory())) {
                ResDictionary dictionary = dictionaryService.getResDictionaryByCode(ss.getCategory());
                sysTenantVo.setCategoryName(dictionary.getDictName());
            }
            // 查询父客户名称
            if (ss.getParentId() != 0L) {
                SysTenant parentTenant = sysTenantMapper.selectById(ss.getParentId());
                if (Objects.nonNull(parentTenant)){
                    sysTenantVo.setParentName(parentTenant.getTenantName());
                }
            }
            sysTenantVos.add(sysTenantVo);
        });
        return sysTenantVos;
    }

    /**
     * 查询客户信息--单条
     *
     * @param tenantAo
     * @return
     */
    public SysTenantVo queryCustomer(SysTenantAo tenantAo) {
        SysTenant sysTenant = sysTenantMapper.selectById(tenantAo.getId());
        SysTenantVo sysTenantVo = new SysTenantVo();
        BeanUtils.copyProperties(sysTenant, sysTenantVo);
        if (StringUtils.isNotBlank(sysTenant.getAddress())) {
            String[] split = sysTenant.getAddress().split(":");
            sysTenantVo.setAddress(split[0]);
            sysTenantVo.setDetailAddress(split[1]);
        }
        // 封装客户类别
        ResDictionary dictionary = dictionaryService.getResDictionaryByCode(sysTenant.getCategory());
        sysTenantVo.setCategoryName(dictionary.getDictName());
        // 查询父客户名称
        if (sysTenant.getParentId() != 0L) {
            SysTenant parentTenant = sysTenantMapper.selectById(sysTenant.getParentId());
            sysTenantVo.setParentName(parentTenant.getTenantName());
        }
        return sysTenantVo;
    }
}
